import os
import json
import copy
import logging
from src.ui.i18n import _
from PySide6.QtWidgets import (
    QDialog, QVBoxLayout, QFormLayout, QLineEdit,
    QPushButton, QDialogButtonBox, QGroupBox, QMessageBox, QComboBox, QSpinBox,
    QHBoxLayout, QCheckBox, QHeaderView, QStyle, QLabel,
    QListWidget, QStackedWidget, QWidget, QListWidgetItem, QTabWidget, QTableWidget, QTableWidgetItem,
    QInputDialog, QListWidget, QListWidgetItem, QProgressDialog, QFileDialog
)
from PySide6.QtCore import Qt, QSize
from src.config import app_config
from src.utils.api_client import fetch_models, test_model_connection
from src.ui.theme import set_theme, get_current_theme, get_available_themes






class ModelEditDialog(QDialog):
    def __init__(self, service_type, model_data=None, parent=None):
        super().__init__(parent)
        self.setWindowTitle(_("Edit Model") if model_data else _("Add Model"))
        self.setMinimumWidth(450)

        self.service_type = service_type
        self.model_data = model_data if model_data else {}

        layout = QVBoxLayout(self)
        form_layout = QFormLayout()
        form_layout.setFieldGrowthPolicy(
            QFormLayout.FieldGrowthPolicy.ExpandingFieldsGrow)

        self.display_name_edit = QLineEdit(
            self.model_data.get("display_name", ""))
        self.model_name_edit = QLineEdit(self.model_data.get("model_name", ""))

        form_layout.addRow(_("Display Name:"), self.display_name_edit)
        form_layout.addRow(_("Model ID:"), self.model_name_edit)

        if self.service_type == 'llm':
            self.supports_no_think_checkbox = QCheckBox(_("Supports No Think"))
            self.supports_no_think_checkbox.setChecked(
                self.model_data.get("supports_no_think", False))
            form_layout.addRow(self.supports_no_think_checkbox)
        elif self.service_type == 'tts':
            self.language_edit = QLineEdit(self.model_data.get("language", ""))
            self.voice_edit = QLineEdit(self.model_data.get("voice", ""))
            form_layout.addRow(_("Language:"), self.language_edit)
            form_layout.addRow(_("Voice:"), self.voice_edit)
        elif self.service_type == 'stt':
            # No specific fields for stt, but we can add them here if needed in the future
            pass

        layout.addLayout(form_layout)

        self.button_box = QDialogButtonBox(
            QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)
        layout.addWidget(self.button_box)

    def get_data(self):
        data = {
            "display_name": self.display_name_edit.text().strip(),
            "model_name": self.model_name_edit.text().strip()
        }
        if self.service_type == 'llm':
            data["supports_no_think"] = self.supports_no_think_checkbox.isChecked()
        elif self.service_type == 'tts':
            data["language"] = self.language_edit.text().strip()
            data["voice"] = self.voice_edit.text().strip()
        elif self.service_type == 'stt':
            # No specific fields for stt, but we can add them here if needed in the future
            pass
        return data


class ImportModelsDialog(QDialog):
    def __init__(self, base_url, api_key, existing_models, parent=None):
        super().__init__(parent)
        self.setWindowTitle(_("Import Models"))
        self.setMinimumSize(400, 300)

        self.existing_models = {m.get("model_name") for m in existing_models}

        layout = QVBoxLayout(self)

        self.model_list_widget = QListWidget()
        layout.addWidget(self.model_list_widget)

        button_layout = QHBoxLayout()
        self.select_all_button = QPushButton(_("Select All"))
        self.deselect_all_button = QPushButton(_("Deselect All"))
        button_layout.addWidget(self.select_all_button)
        button_layout.addWidget(self.deselect_all_button)
        button_layout.addStretch()
        layout.addLayout(button_layout)

        self.button_box = QDialogButtonBox(
            QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
        layout.addWidget(self.button_box)

        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)
        self.select_all_button.clicked.connect(self.select_all)
        self.deselect_all_button.clicked.connect(self.deselect_all)

        self.progress_dialog = QProgressDialog(
            _("Fetching models..."), _("Cancel"), 0, 0, self)
        self.progress_dialog.setWindowModality(Qt.WindowModality.WindowModal)
        self.progress_dialog.show()

        self.fetch_worker = fetch_models(base_url, api_key)
        self.fetch_worker.finished.connect(self.on_fetch_finished)
        self.fetch_worker.start()

    def on_fetch_finished(self, success, result):
        self.progress_dialog.close()
        if success:
            for model in result:
                if model.id not in self.existing_models:
                    item = QListWidgetItem(model.id)
                    item.setFlags(
                        item.flags() | Qt.ItemFlag.ItemIsUserCheckable)
                    item.setCheckState(Qt.CheckState.Unchecked)
                    self.model_list_widget.addItem(item)
        else:
            QMessageBox.critical(self, _("Error"), _(
                "Failed to fetch models: {}").format(result))
            self.reject()

    def select_all(self):
        for i in range(self.model_list_widget.count()):
            self.model_list_widget.item(i).setCheckState(Qt.CheckState.Checked)

    def deselect_all(self):
        for i in range(self.model_list_widget.count()):
            self.model_list_widget.item(
                i).setCheckState(Qt.CheckState.Unchecked)

    def get_selected_models(self):
        selected = []
        for i in range(self.model_list_widget.count()):
            item = self.model_list_widget.item(i)
            if item.checkState() == Qt.CheckState.Checked:
                selected.append({"display_name": item.text(
                ), "model_name": item.text(), "supports_no_think": False})
        return selected


class SettingsDialog(QDialog):
    def __init__(self, translator, parent=None):
        super().__init__(parent)
        self.setWindowTitle(_("Settings"))
        self.logger = logging.getLogger(self.__class__.__name__)
        self.logger.debug("Initializing SettingsDialog...")

        # Main layout
        main_layout = QHBoxLayout(self)

        # Navigation
        self.nav_list = QListWidget()
        self.nav_list.setFixedWidth(180)
        self.nav_list.setObjectName("SettingsNavList")
        main_layout.addWidget(self.nav_list)

        # Content area
        content_container = QWidget()
        content_layout = QVBoxLayout(content_container)
        content_layout.setContentsMargins(10, 10, 10, 10)
        main_layout.addWidget(content_container, 1)

        self.stacked_widget = QStackedWidget()
        content_layout.addWidget(self.stacked_widget)

        # Dialog Buttons
        self.button_box = QDialogButtonBox(
            QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
        content_layout.addWidget(self.button_box)

        # Create and add pages
        self.create_pages()

        # Connect signals
        self.nav_list.currentRowChanged.connect(
            self.stacked_widget.setCurrentIndex)
        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)

        self.load_settings()
        self.retranslate_ui()
        if translator:
            translator.language_changed.connect(self.retranslate_ui)

        self.nav_list.setCurrentRow(0)
        self.resize(900, 650)

    def create_pages(self):
        # Page 1: UI Settings
        ui_page = self._create_ui_page()
        self.stacked_widget.addWidget(ui_page)
        self.ui_nav_item = QListWidgetItem(_("UI Settings"))
        self.nav_list.addItem(self.ui_nav_item)

        # Page 2: Translation Settings
        translation_page = self._create_translation_page()
        self.stacked_widget.addWidget(translation_page)
        self.translation_nav_item = QListWidgetItem(_("Translation"))
        self.nav_list.addItem(self.translation_nav_item)

        # Page 3: Service Providers
        providers_page = self._create_providers_page()
        self.stacked_widget.addWidget(providers_page)
        self.providers_nav_item = QListWidgetItem(_("Service Providers"))
        self.nav_list.addItem(self.providers_nav_item)

        # Page 4: Dubbing Settings
        dubbing_page = self._create_dubbing_page()
        self.stacked_widget.addWidget(dubbing_page)
        self.dubbing_nav_item = QListWidgetItem(_("Dubbing"))
        self.nav_list.addItem(self.dubbing_nav_item)

        # Page 5: Path Settings
        paths_page = self._create_paths_page()
        self.stacked_widget.addWidget(paths_page)
        self.paths_nav_item = QListWidgetItem(_("Paths"))
        self.nav_list.addItem(self.paths_nav_item)

    def _create_ui_page(self):
        page = QWidget()
        layout = QVBoxLayout(page)
        layout.setContentsMargins(0, 0, 0, 0)

        self.ui_group = QGroupBox()
        ui_layout = QFormLayout(self.ui_group)

        self.theme_combo = QComboBox()
        self.theme_combo.addItem(_("Auto"), "auto")
        for theme in get_available_themes():
            self.theme_combo.addItem(theme.capitalize(), theme)
        self.theme_label = QLabel()
        ui_layout.addRow(self.theme_label, self.theme_combo)
        self.theme_combo.activated.connect(self._on_theme_changed)

        self.language_combo = QComboBox()
        self.language_combo.addItem("English", "en-US")
        self.language_combo.addItem("简体中文", "zh-CN")
        self.language_combo.addItem("日本語", "ja-JP")
        self.language_combo.addItem("Français", "fr-FR")
        self.language_combo.addItem("Deutsch", "de-DE")
        self.language_combo.addItem("Русский", "ru-RU")
        self.language_label = QLabel()
        ui_layout.addRow(self.language_label, self.language_combo)
        self.language_combo.activated.connect(self._on_language_changed)

        self.debug_mode_checkbox = QCheckBox()
        self.debug_mode_label = QLabel()
        ui_layout.addRow(self.debug_mode_label, self.debug_mode_checkbox)

        self.show_progress_checkbox = QCheckBox()
        self.show_progress_label = QLabel()
        ui_layout.addRow(self.show_progress_label, self.show_progress_checkbox)

        layout.addWidget(self.ui_group)
        layout.addStretch()
        return page

    def _create_translation_page(self):
        page = QWidget()
        layout = QVBoxLayout(page)
        layout.setContentsMargins(0, 0, 0, 0)

        self.translation_group = QGroupBox()
        translation_layout = QFormLayout(self.translation_group)

        self.default_service_combo = QComboBox()
        self.default_service_combo.addItems(["OpenAI", "Microsoft"])
        self.source_lang_edit = QLineEdit()
        self.target_lang_edit = QLineEdit()
        self.batch_size_edit = QLineEdit()
        self.openai_max_workers_spin = QSpinBox()
        self.openai_max_workers_spin.setRange(1, 100)
        self.video_types_edit = QLineEdit()
        self.translation_styles_edit = QLineEdit()

        self.default_service_label = QLabel()
        self.source_lang_label = QLabel()
        self.target_lang_label = QLabel()
        self.batch_size_label = QLabel()
        self.openai_max_workers_label = QLabel()
        self.video_types_label = QLabel()
        self.translation_styles_label = QLabel()

        translation_layout.addRow(
            self.default_service_label, self.default_service_combo)
        translation_layout.addRow(
            self.source_lang_label, self.source_lang_edit)
        translation_layout.addRow(
            self.target_lang_label, self.target_lang_edit)
        translation_layout.addRow(self.batch_size_label, self.batch_size_edit)
        translation_layout.addRow(self.openai_max_workers_label, self.openai_max_workers_spin)
        translation_layout.addRow(
            self.video_types_label, self.video_types_edit)
        translation_layout.addRow(
            self.translation_styles_label, self.translation_styles_edit)

        layout.addWidget(self.translation_group)
        layout.addStretch()
        return page

    def _create_providers_page(self):
        page = QWidget()
        layout = QVBoxLayout(page)
        layout.setContentsMargins(0, 0, 0, 0)

        # Top bar for provider selection and management
        top_bar_layout = QHBoxLayout()
        self.provider_combo_label = QLabel(_("Service Provider:"))
        self.provider_combo = QComboBox()
        self.add_provider_button = QPushButton()
        self.remove_provider_button = QPushButton()
        self.edit_provider_button = QPushButton()

        top_bar_layout.addWidget(self.provider_combo_label)
        top_bar_layout.addWidget(self.provider_combo, 1)
        top_bar_layout.addWidget(self.add_provider_button)
        top_bar_layout.addWidget(self.edit_provider_button)
        top_bar_layout.addWidget(self.remove_provider_button)
        layout.addLayout(top_bar_layout)

        # Stacked widget to show settings for the selected provider
        self.provider_stack = QStackedWidget()
        layout.addWidget(self.provider_stack, 1)

        self.provider_combo.currentIndexChanged.connect(
            self.provider_stack.setCurrentIndex)
        # Connections for buttons will be added later
        self.add_provider_button.clicked.connect(self.add_provider)
        self.edit_provider_button.clicked.connect(self.edit_provider)
        self.remove_provider_button.clicked.connect(self.remove_provider)

        return page

    def _create_dubbing_page(self):
        page = QWidget()
        layout = QVBoxLayout(page)
        layout.setContentsMargins(0, 0, 0, 0)

        self.dubbing_group = QGroupBox()
        dubbing_layout = QFormLayout(self.dubbing_group)
        self.dubbing_concurrent_tasks_spin = QSpinBox()
        self.dubbing_concurrent_tasks_spin.setRange(1, 100)
        self.dubbing_concurrent_tasks_label = QLabel()
        dubbing_layout.addRow(
            self.dubbing_concurrent_tasks_label, self.dubbing_concurrent_tasks_spin)

        layout.addWidget(self.dubbing_group)
        layout.addStretch()
        return page

    def _create_paths_page(self):
        page = QWidget()
        layout = QVBoxLayout(page)
        layout.setContentsMargins(0, 0, 0, 0)

        self.paths_group = QGroupBox()
        paths_layout = QFormLayout(self.paths_group)

        self.workspace_dir_edit = QLineEdit()
        self.workspace_dir_label = QLabel()

        self.browse_button = QPushButton(_("Browse..."))
        self.browse_button.clicked.connect(self._select_workspace_directory)

        workspace_layout = QHBoxLayout()
        workspace_layout.addWidget(self.workspace_dir_edit)
        workspace_layout.addWidget(self.browse_button)

        paths_layout.addRow(self.workspace_dir_label, workspace_layout)

        layout.addWidget(self.paths_group)
        layout.addStretch()
        return page

    def _select_workspace_directory(self):
        directory = QFileDialog.getExistingDirectory(
            self,
            _("Select Workspace Directory"),
            self.workspace_dir_edit.text()
        )
        if directory:
            self.workspace_dir_edit.setText(directory)

    def load_settings(self):
        self.logger.debug("Loading settings into dialog...")
        try:
            # UI
            current_theme = get_current_theme()
            index = self.theme_combo.findData(current_theme)
            if index != -1:
                self.theme_combo.setCurrentIndex(index)

            current_lang = app_config.get("ui.language", "zh_CN")
            index = self.language_combo.findData(current_lang)
            if index != -1:
                self.language_combo.setCurrentIndex(index)
            
            self.debug_mode_checkbox.setChecked(app_config.get("app.debug", False))
            self.show_progress_checkbox.setChecked(app_config.get("app.show_progress", False))

            # Translation
            self.default_service_combo.setCurrentText(
                app_config.get("translation.default_service", "OpenAI"))
            self.source_lang_edit.setText(app_config.get(
                "translation.default_source_lang", "auto"))
            self.target_lang_edit.setText(app_config.get(
                "translation.default_target_lang", "zh"))
            self.batch_size_edit.setText(
                str(app_config.get("translation.batch_size", 20)))
            self.openai_max_workers_spin.setValue(
                app_config.get("translation.openai_max_workers", 5))
            video_types = app_config.get("translation.video_types", [
                                         "Regular", "Course", "Commentary", "Gaming"])
            self.video_types_edit.setText(", ".join(video_types))
            translation_styles = app_config.get("translation.translation_styles", [
                                                "Regular", "Cute", "Anime", "Chunibyo", "Classical", "Formal", "Humorous"])
            self.translation_styles_edit.setText(", ".join(translation_styles))

            # Service Providers
            self.load_providers()

            # Dubbing
            self.dubbing_concurrent_tasks_spin.setValue(
                app_config.get("dubbing.concurrent_tasks", 10))

            # Paths
            self.workspace_dir_edit.setText(
                app_config.get("paths.workspace", "trans"))

            self.logger.debug("All settings loaded successfully.")
        except Exception as e:
            self.logger.error(f"Failed to load settings: {e}", exc_info=True)
            QMessageBox.critical(self, _("Failed to load settings"), _(
                "An error occurred while loading the configuration: {}").format(e))

    def _on_theme_changed(self, index):
        selected_theme = self.theme_combo.itemData(index)
        if selected_theme:
            self.logger.info(
                _("Theme changed to: {}, applying immediately.").format(selected_theme))
            set_theme(selected_theme)

    def _on_language_changed(self, index):
        selected_lang = self.language_combo.itemData(index)
        if selected_lang:
            if selected_lang == app_config.get('ui.language'):
                return

            self.logger.info(
                _("Language changed to: {}, applying immediately.").format(selected_lang))
            app_config.set('ui.language', selected_lang, emit_signal=True)
            try:
                app_config.save()
                self.logger.debug(
                    _("Language '{}' saved to config.").format(selected_lang))
            except IOError as e:
                self.logger.error(f"Failed to save language immediately: {e}")
                QMessageBox.critical(self, _("Failed to save language"), _(
                    "Could not write to configuration file: {}").format(e))

    def accept(self):
        # UI settings are applied instantly. Only save other settings.
        app_config.set('app.debug', self.debug_mode_checkbox.isChecked(), emit_signal=False)
        app_config.set('app.show_progress', self.show_progress_checkbox.isChecked(), emit_signal=False)

        # Translation
        app_config.set('translation.default_service',
                       self.default_service_combo.currentText(), emit_signal=False)
        app_config.set('translation.default_source_lang',
                       self.source_lang_edit.text().strip(), emit_signal=False)
        app_config.set('translation.default_target_lang',
                       self.target_lang_edit.text().strip(), emit_signal=False)
        try:
            app_config.set('translation.batch_size', int(
                self.batch_size_edit.text().strip()), emit_signal=False)
        except ValueError:
            pass

        app_config.set('translation.openai_max_workers',
                       self.openai_max_workers_spin.value(), emit_signal=False)

        video_types = [v.strip() for v in self.video_types_edit.text(
        ).strip().split(',') if v.strip()]
        app_config.set('translation.video_types',
                       video_types, emit_signal=False)
        translation_styles = [s.strip() for s in self.translation_styles_edit.text(
        ).strip().split(',') if s.strip()]
        app_config.set('translation.translation_styles',
                       translation_styles, emit_signal=False)

        # Service Providers
        self.save_providers()

        # Dubbing
        app_config.set('dubbing.concurrent_tasks',
                       self.dubbing_concurrent_tasks_spin.value(), emit_signal=False)

        # Paths
        app_config.set(
            'paths.workspace', self.workspace_dir_edit.text().strip(), emit_signal=False)

        try:
            app_config.save()
            super().accept()
        except IOError as e:
            QMessageBox.critical(self, _("Failed to save settings"), _(
                "Could not write to configuration file: {}").format(e))

    def retranslate_ui(self):
        self.logger.debug("Retranslating SettingsDialog...")
        self.setWindowTitle(_("Settings"))

        # --- Nav List ---
        self.ui_nav_item.setText(_("UI Settings"))
        self.translation_nav_item.setText(_("Translation"))
        self.providers_nav_item.setText(_("Service Providers"))
        self.dubbing_nav_item.setText(_("Dubbing"))
        self.paths_nav_item.setText(_("Paths"))

        # --- UI Settings Group ---
        self.ui_group.setTitle(_("UI Settings"))
        self.theme_label.setText(_("Theme:"))
        self.language_label.setText(_("Language:"))
        self.debug_mode_label.setText(_("Debug Mode:"))
        self.debug_mode_checkbox.setToolTip(
            _("Enable detailed debug logging in the console and log files."))
        self.show_progress_label.setText(_("Show Detailed Progress:"))
        self.show_progress_checkbox.setToolTip(
            _("Show detailed progress updates in the UI log window."))
        self.video_types_edit.setToolTip(
            _("Enter multiple video types, separated by commas (,)."))
        self.translation_styles_edit.setToolTip(
            _("Enter multiple translation styles, separated by commas (,)."))

        # --- Translation Group ---
        self.translation_group.setTitle(_("Translation Settings"))
        self.default_service_label.setText(_("Default Translation Service:"))
        self.source_lang_label.setText(_("Default Source Language:"))
        self.target_lang_label.setText(_("Default Target Language:"))
        self.batch_size_label.setText(_("Translation Batch Size:"))
        self.openai_max_workers_label.setText(_("OpenAI Max Concurrent Requests:"))
        self.video_types_label.setText(_("Video Types:"))
        self.translation_styles_label.setText(_("Translation Styles:"))

        # --- Service Provider Page ---
        self.provider_combo_label.setText(_("Service Provider:"))
        self.add_provider_button.setText(_("Add"))
        self.edit_provider_button.setText(_("Edit"))
        self.remove_provider_button.setText(_("Remove"))
        self.add_provider_button.setToolTip(_("Add a new service provider"))
        self.edit_provider_button.setToolTip(
            _("Edit the selected service provider"))
        self.remove_provider_button.setToolTip(
            _("Remove the selected service provider"))

        # --- Dubbing Group ---
        self.dubbing_group.setTitle(_("Dubbing Settings"))
        self.dubbing_concurrent_tasks_label.setText(_("Concurrent Tasks:"))
        self.dubbing_concurrent_tasks_spin.setToolTip(
            _("Number of concurrent tasks for generating dubbing."))

        # --- Paths Group ---
        self.paths_group.setTitle(_("Path Settings"))
        self.workspace_dir_label.setText(_("Workspace Directory:"))
        self.browse_button.setText(_("Browse..."))

        # --- Dialog Buttons ---
        self.button_box.button(
            QDialogButtonBox.StandardButton.Ok).setText(_("OK"))
        self.button_box.button(
            QDialogButtonBox.StandardButton.Cancel).setText(_("Cancel"))
        self.logger.debug("SettingsDialog retranslated.")

    def add_provider(self):
        provider_name, ok = QInputDialog.getText(
            self, _("Add Provider"), _("Enter new provider name:"))
        if ok and provider_name:
            for i in range(self.provider_combo.count()):
                if self.provider_combo.itemText(i) == provider_name:
                    QMessageBox.warning(self, _("Duplicate Name"), _(
                        "A provider with this name already exists."))
                    return

            self.logger.info(f"Adding new provider: {provider_name}")
            new_provider_data = {
                "provider_name": provider_name, "api_key": "", "enabled": True,
                "services": {
                    "llm": {"base_url": "", "models": []},
                    "tts": {"base_url": "", "models": []},
                    "stt": {"base_url": "", "models": []}
                }
            }
            self.provider_combo.addItem(provider_name)
            provider_page = self._create_single_provider_page(
                new_provider_data)
            self.provider_stack.addWidget(provider_page)
            index = self.provider_combo.findText(provider_name)
            self.provider_combo.setCurrentIndex(index)

    def edit_provider(self):
        current_index = self.provider_combo.currentIndex()
        if current_index < 0:
            return

        old_name = self.provider_combo.itemText(current_index)
        new_name, ok = QInputDialog.getText(
            self, _("Edit Provider Name"), _("Enter new name:"), text=old_name)

        if ok and new_name and new_name != old_name:
            for i in range(self.provider_combo.count()):
                if i != current_index and self.provider_combo.itemText(i) == new_name:
                    QMessageBox.warning(self, _("Duplicate Name"), _(
                        "A provider with this name already exists."))
                    return
            self.logger.info(f"Renaming provider '{old_name}' to '{new_name}'")
            self.provider_combo.setItemText(current_index, new_name)

    def remove_provider(self):
        current_index = self.provider_combo.currentIndex()
        if current_index < 0:
            return

        provider_name = self.provider_combo.itemText(current_index)
        reply = QMessageBox.question(
            self,
            _("Confirm Removal"),
            _("Are you sure you want to remove the provider '{}'?").format(
                provider_name),
            QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
            QMessageBox.StandardButton.No
        )

        if reply == QMessageBox.StandardButton.Yes:
            self.logger.info(
                f"Removing provider at index {current_index}: {provider_name}")

            page_widget = self.provider_stack.widget(current_index)
            self.provider_stack.removeWidget(page_widget)
            page_widget.deleteLater()

            self.provider_combo.removeItem(current_index)

            self.logger.info(f"Provider '{provider_name}' removed from UI.")

    def import_models(self, service_type, model_table):
        current_provider_page = self.provider_stack.currentWidget()
        if not current_provider_page:
            return

        api_key_edit = current_provider_page.findChild(QLineEdit)
        services_tabs = current_provider_page.findChild(QTabWidget)
        current_service_tab = services_tabs.currentWidget()
        base_url_edit = current_service_tab.findChild(QLineEdit)

        api_key = api_key_edit.text().strip() if api_key_edit else ""
        base_url = base_url_edit.text().strip() if base_url_edit else ""

        if not api_key or not base_url:
            QMessageBox.warning(self, _("Missing Information"), _(
                "API Key and Base URL are required to import models."))
            return

        existing_models = []
        for row in range(model_table.rowCount()):
            existing_models.append(
                {"model_name": model_table.item(row, 1).text()})

        dialog = ImportModelsDialog(base_url, api_key, existing_models, self)
        if dialog.exec():
            selected_models = dialog.get_selected_models()
            for model_data in selected_models:
                row_count = model_table.rowCount()
                model_table.insertRow(row_count)
                model_table.setItem(row_count, 0, QTableWidgetItem(
                    model_data["display_name"]))
                model_table.setItem(
                    row_count, 1, QTableWidgetItem(model_data["model_name"]))

                checkbox_widget = QWidget()
                chk_layout = QHBoxLayout(checkbox_widget)
                chk_layout.setContentsMargins(0, 0, 0, 0)
                chk_layout.setAlignment(Qt.AlignmentFlag.AlignCenter)
                supports_no_think_checkbox = QCheckBox()
                supports_no_think_checkbox.setChecked(
                    model_data["supports_no_think"])
                supports_no_think_checkbox.setEnabled(False)
                chk_layout.addWidget(supports_no_think_checkbox)
                model_table.setCellWidget(row_count, 2, checkbox_widget)
            self.logger.info(f"Imported {len(selected_models)} new models.")

    def add_model(self, service_type, model_table):
        dialog = ModelEditDialog(service_type, parent=self)
        if dialog.exec():
            new_model_data = dialog.get_data()
            if not new_model_data.get("display_name") or not new_model_data.get("model_name"):
                QMessageBox.warning(self, _("Invalid Input"), _(
                    "Display Name and Model ID cannot be empty."))
                return

            row_count = model_table.rowCount()
            model_table.insertRow(row_count)

            if service_type == 'llm':
                model_table.setItem(row_count, 0, QTableWidgetItem(
                    new_model_data.get("display_name", "")))
                model_table.setItem(row_count, 1, QTableWidgetItem(
                    new_model_data.get("model_name", "")))

                checkbox_widget = QWidget()
                chk_layout = QHBoxLayout(checkbox_widget)
                chk_layout.setContentsMargins(0, 0, 0, 0)
                chk_layout.setAlignment(Qt.AlignmentFlag.AlignCenter)
                supports_no_think_checkbox = QCheckBox()
                supports_no_think_checkbox.setChecked(
                    new_model_data.get("supports_no_think", False))
                supports_no_think_checkbox.setEnabled(False)
                chk_layout.addWidget(supports_no_think_checkbox)
                model_table.setCellWidget(row_count, 2, checkbox_widget)

            elif service_type == 'tts':
                model_table.setItem(row_count, 0, QTableWidgetItem(
                    new_model_data.get("display_name", "")))
                model_table.setItem(row_count, 1, QTableWidgetItem(
                    new_model_data.get("model_name", "")))
                model_table.setItem(row_count, 2, QTableWidgetItem(
                    new_model_data.get("language", "")))
                model_table.setItem(row_count, 3, QTableWidgetItem(
                    new_model_data.get("voice", "")))
            elif service_type == 'stt':
                model_table.setItem(row_count, 0, QTableWidgetItem(
                    new_model_data.get("display_name", "")))
                model_table.setItem(row_count, 1, QTableWidgetItem(
                    new_model_data.get("model_name", "")))

            self.logger.info(
                f"Added new {service_type} model: {new_model_data['display_name']}")

    def edit_model(self, service_type, model_table):
        selected_rows = model_table.selectionModel().selectedRows()
        if not selected_rows:
            QMessageBox.warning(self, _("No Model Selected"), _(
                "Please select a model to edit."))
            return

        row = selected_rows[0].row()

        current_model_data = {}
        if service_type == 'llm':
            current_model_data['display_name'] = model_table.item(
                row, 0).text()
            current_model_data['model_name'] = model_table.item(row, 1).text()
            chk_widget = model_table.cellWidget(row, 2)
            chk = chk_widget.findChild(QCheckBox)
            current_model_data['supports_no_think'] = chk.isChecked()
        elif service_type == 'tts':
            current_model_data['display_name'] = model_table.item(
                row, 0).text()
            current_model_data['model_name'] = model_table.item(row, 1).text()
            current_model_data['language'] = model_table.item(row, 2).text()
            current_model_data['voice'] = model_table.item(row, 3).text()
        elif service_type == 'stt':
            current_model_data['display_name'] = model_table.item(
                row, 0).text()
            current_model_data['model_name'] = model_table.item(row, 1).text()

        dialog = ModelEditDialog(
            service_type, model_data=current_model_data, parent=self)
        if dialog.exec():
            updated_model_data = dialog.get_data()
            if not updated_model_data.get("display_name") or not updated_model_data.get("model_name"):
                QMessageBox.warning(self, _("Invalid Input"), _(
                    "Display Name and Model ID cannot be empty."))
                return

            if service_type == 'llm':
                model_table.item(row, 0).setText(
                    updated_model_data.get("display_name", ""))
                model_table.item(row, 1).setText(
                    updated_model_data.get("model_name", ""))
                chk_widget = model_table.cellWidget(row, 2)
                chk = chk_widget.findChild(QCheckBox)
                chk.setChecked(updated_model_data.get(
                    "supports_no_think", False))
            elif service_type == 'tts':
                model_table.item(row, 0).setText(
                    updated_model_data.get("display_name", ""))
                model_table.item(row, 1).setText(
                    updated_model_data.get("model_name", ""))
                model_table.item(row, 2).setText(
                    updated_model_data.get("language", ""))
                model_table.item(row, 3).setText(
                    updated_model_data.get("voice", ""))
            elif service_type == 'stt':
                model_table.item(row, 0).setText(
                    updated_model_data.get("display_name", ""))
                model_table.item(row, 1).setText(
                    updated_model_data.get("model_name", ""))

            self.logger.info(
                f"Edited {service_type} model at row {row}: {updated_model_data['display_name']}")

    def test_model(self, service_type, model_table):
        if service_type.lower() != 'llm':
            QMessageBox.information(self, _("Not Applicable"), _(
                "Model testing is only available for LLM services."))
            return

        selected_rows = model_table.selectionModel().selectedRows()
        if not selected_rows:
            QMessageBox.warning(self, _("No Model Selected"), _(
                "Please select a model to test."))
            return

        row = selected_rows[0].row()
        model_name = model_table.item(row, 1).text()

        current_provider_page = self.provider_stack.currentWidget()
        if not current_provider_page:
            return

        api_key_edit = current_provider_page.findChild(QLineEdit)
        services_tabs = current_provider_page.findChild(QTabWidget)
        current_service_tab = services_tabs.currentWidget()
        base_url_edit = current_service_tab.findChild(QLineEdit)

        api_key = api_key_edit.text().strip() if api_key_edit else ""
        base_url = base_url_edit.text().strip() if base_url_edit else ""

        if not api_key or not base_url:
            QMessageBox.warning(self, _("Missing Information"), _(
                "API Key and Base URL are required to test models."))
            return

        self.progress_dialog = QProgressDialog(
            _("Testing model..."), _("Cancel"), 0, 0, self)
        self.progress_dialog.setWindowModality(Qt.WindowModality.WindowModal)
        self.progress_dialog.show()

        self.test_worker = test_model_connection(base_url, api_key, model_name)
        self.test_worker.finished.connect(self.on_test_finished)
        self.test_worker.start()

    def on_test_finished(self, success, message):
        self.progress_dialog.close()
        if success:
            QMessageBox.information(self, _("Test Result"), message)
        else:
            QMessageBox.critical(self, _("Test Result"), message)

    def remove_model(self, service_type, model_table):
        selected_rows = model_table.selectionModel().selectedRows()
        if not selected_rows:
            QMessageBox.warning(self, _("No Model Selected"), _(
                "Please select a model to remove."))
            return

        reply = QMessageBox.question(
            self,
            _("Confirm Removal"),
            _("Are you sure you want to remove the selected model(s)?"),
            QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
            QMessageBox.StandardButton.No
        )

        if reply == QMessageBox.StandardButton.Yes:
            # Sort rows in descending order to avoid index shifting issues
            for index in sorted(selected_rows, key=lambda x: x.row(), reverse=True):
                model_name = model_table.item(index.row(), 0).text()
                self.logger.info(
                    f"Removing model at row {index.row()}: {model_name}")
                model_table.removeRow(index.row())
            self.logger.info("Model(s) removed from UI.")

    def load_providers(self):
        self.provider_combo.blockSignals(True)

        self.provider_combo.clear()
        while self.provider_stack.count() > 0:
            widget = self.provider_stack.widget(0)
            self.provider_stack.removeWidget(widget)
            widget.deleteLater()

        providers = app_config.get("service_providers", [])
        for i, provider_data in enumerate(providers):
            provider_name = provider_data.get(
                "provider_name", f"Provider {i+1}")
            self.provider_combo.addItem(provider_name, userData=provider_data)

            provider_page = self._create_single_provider_page(provider_data)
            self.provider_stack.addWidget(provider_page)

        self.provider_combo.blockSignals(False)
        if self.provider_combo.count() > 0:
            self.provider_combo.setCurrentIndex(0)
            self.provider_stack.setCurrentIndex(0)

    def _create_single_provider_page(self, provider_data):
        page = QWidget()
        page.setProperty("provider_data", provider_data)
        layout = QVBoxLayout(page)
        layout.setContentsMargins(10, 10, 10, 10)

        details_group = QGroupBox(_("Provider Details"))
        details_layout = QFormLayout(details_group)
        details_layout.setFieldGrowthPolicy(
            QFormLayout.FieldGrowthPolicy.ExpandingFieldsGrow)
        api_key_edit = QLineEdit(provider_data.get("api_key", ""))
        api_key_edit.setObjectName("api_key_edit")
        enabled_checkbox = QCheckBox(_("Enabled"))
        enabled_checkbox.setObjectName("enabled_checkbox")
        enabled_checkbox.setChecked(provider_data.get("enabled", True))
        details_layout.addRow(_("API Key:"), api_key_edit)
        details_layout.addRow(enabled_checkbox)
        layout.addWidget(details_group)

        services_tabs = QTabWidget()
        layout.addWidget(services_tabs, 1)
        page.setProperty("services_tabs", services_tabs)

        services = provider_data.get("services", {})
        if not services:
            no_services_label = QLabel(
                _("No services configured for this provider."))
            no_services_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
            layout.addWidget(no_services_label)
        else:
            for service_type, service_data in services.items():
                service_tab = self._create_service_tab(
                    service_type, service_data)
                services_tabs.addTab(service_tab, service_type.upper())

        return page

    def _create_service_tab(self, service_type, service_data):
        tab = QWidget()
        layout = QVBoxLayout(tab)
        layout.setContentsMargins(5, 10, 5, 5)

        form_layout = QFormLayout()
        form_layout.setFieldGrowthPolicy(
            QFormLayout.FieldGrowthPolicy.ExpandingFieldsGrow)
        base_url_edit = QLineEdit(service_data.get("base_url", ""))
        base_url_edit.setObjectName("base_url_edit")
        form_layout.addRow(_("Base URL:"), base_url_edit)
        layout.addLayout(form_layout)

        model_group = QGroupBox(_("Models"))
        model_layout = QVBoxLayout(model_group)
        layout.addWidget(model_group, 1)

        model_table = QTableWidget()
        model_table.setSelectionBehavior(
            QTableWidget.SelectionBehavior.SelectRows)
        model_table.setEditTriggers(QTableWidget.EditTrigger.NoEditTriggers)
        model_layout.addWidget(model_table, 1)

        models = service_data.get("models", [])
        model_table.setRowCount(len(models))

        if service_type.lower() == 'llm':
            model_table.setColumnCount(3)
            model_table.setHorizontalHeaderLabels(
                [_("Display Name"), _("Model ID"), _("Supports No Think")])
            for row, model_data in enumerate(models):
                model_table.setItem(row, 0, QTableWidgetItem(
                    model_data.get("display_name", "")))
                model_table.setItem(row, 1, QTableWidgetItem(
                    model_data.get("model_name", "")))

                checkbox_widget = QWidget()
                chk_layout = QHBoxLayout(checkbox_widget)
                chk_layout.setContentsMargins(0, 0, 0, 0)
                chk_layout.setAlignment(Qt.AlignmentFlag.AlignCenter)
                supports_no_think_checkbox = QCheckBox()
                supports_no_think_checkbox.setChecked(
                    model_data.get("supports_no_think", False))
                supports_no_think_checkbox.setEnabled(False)
                chk_layout.addWidget(supports_no_think_checkbox)
                model_table.setCellWidget(row, 2, checkbox_widget)

        elif service_type.lower() == 'tts':
            model_table.setColumnCount(4)
            model_table.setHorizontalHeaderLabels(
                [_("Display Name"), _("Model ID"), _("Language"), _("Voice")])
            for row, model_data in enumerate(models):
                model_table.setItem(row, 0, QTableWidgetItem(
                    model_data.get("display_name", "")))
                model_table.setItem(row, 1, QTableWidgetItem(
                    model_data.get("model_name", "")))
                model_table.setItem(row, 2, QTableWidgetItem(
                    model_data.get("language", "")))
                model_table.setItem(row, 3, QTableWidgetItem(
                    model_data.get("voice", "")))
        elif service_type.lower() == 'stt':
            model_table.setColumnCount(2)
            model_table.setHorizontalHeaderLabels(
                [_("Display Name"), _("Model ID")])
            for row, model_data in enumerate(models):
                model_table.setItem(row, 0, QTableWidgetItem(
                    model_data.get("display_name", "")))
                model_table.setItem(row, 1, QTableWidgetItem(
                    model_data.get("model_name", "")))

        model_table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.Stretch)

        model_buttons_layout = QHBoxLayout()
        import_models_button = QPushButton(_("Import Models"))
        add_model_button = QPushButton(_("Add"))
        edit_model_button = QPushButton(_("Edit"))
        remove_model_button = QPushButton(_("Remove"))
        test_model_button = QPushButton(_("Test"))

        model_buttons_layout.addWidget(import_models_button)
        model_buttons_layout.addWidget(test_model_button)
        model_buttons_layout.addStretch()
        model_buttons_layout.addWidget(add_model_button)
        model_buttons_layout.addWidget(edit_model_button)
        model_buttons_layout.addWidget(remove_model_button)
        model_layout.addLayout(model_buttons_layout)

        # Connect model buttons
        import_models_button.clicked.connect(
            lambda: self.import_models(service_type, model_table))
        test_model_button.clicked.connect(
            lambda: self.test_model(service_type, model_table))
        add_model_button.clicked.connect(
            lambda: self.add_model(service_type, model_table))
        edit_model_button.clicked.connect(
            lambda: self.edit_model(service_type, model_table))
        remove_model_button.clicked.connect(
            lambda: self.remove_model(service_type, model_table))

        if service_type.lower() not in ["llm", "stt"]:
            import_models_button.setEnabled(False)
            import_models_button.setToolTip(
                _("Model import is only available for LLM and STT services."))
        if service_type.lower() != "llm":
            test_model_button.setEnabled(False)
            test_model_button.setToolTip(
                _("Model testing is only available for LLM services."))

        return tab

    def save_providers(self):
        self.logger.debug(_("Saving provider settings..."))
        new_providers_list = []
        for i in range(self.provider_stack.count()):
            provider_page = self.provider_stack.widget(i)
            provider_name = self.provider_combo.itemText(i)

            # Find provider details widgets
            api_key_edit = provider_page.findChild(QLineEdit, "api_key_edit")
            enabled_checkbox = provider_page.findChild(QCheckBox, "enabled_checkbox")

            new_provider_data = {
                "provider_name": provider_name,
                "api_key": api_key_edit.text() if api_key_edit else "",
                "enabled": enabled_checkbox.isChecked() if enabled_checkbox else True,
                "services": {}
            }

            services_tabs = provider_page.findChild(QTabWidget)
            if services_tabs:
                for j in range(services_tabs.count()):
                    service_type = services_tabs.tabText(j).lower()
                    service_tab = services_tabs.widget(j)

                    base_url_edit = service_tab.findChild(QLineEdit, "base_url_edit")
                    model_table = service_tab.findChild(QTableWidget)

                    new_service_data = {
                        "base_url": base_url_edit.text() if base_url_edit else "",
                        "models": []
                    }

                    if model_table:
                        for row in range(model_table.rowCount()):
                            model_data = {}
                            if service_type == 'llm':
                                model_data["display_name"] = model_table.item(
                                    row, 0).text()
                                model_data["model_name"] = model_table.item(
                                    row, 1).text()
                                chk_widget = model_table.cellWidget(row, 2)
                                chk = chk_widget.findChild(QCheckBox)
                                model_data["supports_no_think"] = chk.isChecked()
                            elif service_type == 'tts':
                                model_data["display_name"] = model_table.item(
                                    row, 0).text()
                                model_data["model_name"] = model_table.item(
                                    row, 1).text()
                                model_data["language"] = model_table.item(
                                    row, 2).text()
                                model_data["voice"] = model_table.item(
                                    row, 3).text()
                            elif service_type == 'stt':
                                model_data["display_name"] = model_table.item(
                                    row, 0).text()
                                model_data["model_name"] = model_table.item(
                                    row, 1).text()

                            new_service_data["models"].append(model_data)

                    new_provider_data["services"][service_type] = new_service_data

            new_providers_list.append(new_provider_data)

        app_config.set("service_providers",
                       new_providers_list, emit_signal=False)
        self.logger.debug(_("Provider settings prepared for saving."))
